/*
 * Aboboo Android
 * Copyright (C) 2012 www.aboboo.com
 * 
 */
package com.aboboo.android.player;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import android.util.Log;

/**
 * 
 * @author fangpeng
 * 
 * @version 1.0 2013-01-31
 * 
 */
public class LyricAdapter {
	private ArrayList<LyricLine> mLyricLines = null;
	private LyricListener mListener = null; // 歌词载入，变化Listener
	private int mCurrentLyric = 0; // 当前的歌词
	private int mLyricOffset = -300; // 为了解决播放滞后的问题设置的调整时间，单位是毫秒
	private static final String TAG = "LyricAdapter";

	// 用于向外通知歌词载入，变化的Listener
	public interface LyricListener {
		public void onLyricChanged(int lyric_index);

		public void onLyricLoaded();
	}

	// 歌词信息
	private class LyricLine {
		long mLyricTime; // in milliseconds
		String mLyricText;

		LyricLine(long time, String lyric) {
			mLyricTime = time;
			mLyricText = lyric;
		}
	}

	// 将歌词的时间字符串转化成毫秒数的Utility类，如果参数是00:01:23.45
	private static class TimeParser {
		// @return value in milliseconds.
		static long parse(String strTime) {
			String beforeDot = new String("00:00:00");
			String afterDot = new String("0");

			// 将字符串按小数点拆分成整秒部分和小数部分。
			int dotIndex = strTime.indexOf(".");
			if (dotIndex < 0) {
				beforeDot = strTime;
			} else if (dotIndex == 0) {
				afterDot = strTime.substring(1);
			} else {
				beforeDot = strTime.substring(0, dotIndex);// 00:01:23
				afterDot = strTime.substring(dotIndex + 1); // 45
			}

			long intSeconds = 0;
			int counter = 0;
			while (beforeDot.length() > 0) {
				int colonPos = beforeDot.indexOf(":");
				try {
					if (colonPos > 0) {// 找到冒号了。
						intSeconds *= 60;
						intSeconds += Integer.valueOf((beforeDot.substring(0,
								colonPos)));
						beforeDot = beforeDot.substring(colonPos + 1);
					} else if (colonPos < 0) {// 没找到，剩下都当一个数处理了。
						intSeconds *= 60;
						intSeconds += Integer.valueOf((beforeDot));
						beforeDot = "";
					} else {// 第一个就是冒号，不可能！
						return -1;
					}
				} catch (NumberFormatException e) {
					return -1;
				}
				++counter;
				if (counter > 3) {// 不会超过小时，分，秒吧。
					return -1;
				}
			}
			// intSeconds=83

			String totalTime = String.format("%d.%s", intSeconds, afterDot);// totaoTimer
																			// =
																			// "83.45"
			Double doubleSeconds = Double.valueOf(totalTime); // 转成小数83.25
			return (long) (doubleSeconds * 1000);// 转成毫秒8345
		}
	}

	// 歌词读入
	public void LoadLyric(String path) {
		mLyricLines = new ArrayList<LyricLine>();
		mLyricLines.clear();
		mCurrentLyric = -1;
		try {
			FileReader fr = new FileReader(path);
			BufferedReader br = new BufferedReader(fr);

			String line;
			while ((line = br.readLine()) != null) {// 读出一行
				int timeEndIndex = line.lastIndexOf("]");// 找到歌词时间的最后位置
				if (timeEndIndex >= 3) {// 最起码[1]程度应该有吧。
					String lyricText = new String();
					// 先取出歌词
					if (timeEndIndex < (line.length() - 1)) {
						lyricText = line.substring(timeEndIndex + 1,
								line.length());
					}

					// 处理重复的歌词,如下面的例子
					// [时间1][时间2][时间3][时间4]歌词
					int timeSegmentEnd = timeEndIndex;
					while (timeSegmentEnd > 0) {
						timeEndIndex = line.lastIndexOf("]", timeSegmentEnd);
						if (timeEndIndex < 1)
							break; // 没找到"]"，算了
						int timeStartIndex = line.lastIndexOf("[",
								timeEndIndex - 1);
						if (timeStartIndex < 0)
							break; // 没找到"["，算了
						// "["和"]"都找到了，取出时间字符串
						long lyricTime = TimeParser.parse(line.substring(
								timeStartIndex + 1, timeEndIndex));
						if (lyricTime >= 0) {
							lyricTime += mLyricOffset;// 调整时间
							if (lyricTime < 0) {
								lyricTime = 0;// 也别太小了。
							}
							// 行了，保存一句。
							mLyricLines
									.add(new LyricLine(lyricTime, lyricText));
						}
						timeSegmentEnd = timeStartIndex;
					}
				}
			}
			// 按时间排序
			Collections.sort(mLyricLines, new Comparator<LyricLine>() {
				// 内嵌，匿名的compare类
				public int compare(LyricLine object1, LyricLine object2) {
					if (object1.mLyricTime > object2.mLyricTime) {
						return 1;
					} else if (object1.mLyricTime < object2.mLyricTime) {
						return -1;
					} else {
						return 0;
					}
				}
			});
			fr.close();

		} catch (FileNotFoundException e) {
			mLyricLines = null;
			e.printStackTrace();
		} catch (IOException e) {
			mLyricLines = null;
			e.printStackTrace();
		}
		if (mListener != null) {
			// 如果有人想知道，告诉一声，歌词已经读进来了。
			mListener.onLyricLoaded();
		}
	}

	public int getLyricCount() {
		if (mLyricLines != null) {
			return mLyricLines.size();
		} else {
			return 0;
		}
	}

	public String getLyric(int index) {
		if (mLyricLines != null) {
			if (index >= 0 && index < mLyricLines.size()) {
				return mLyricLines.get(index).mLyricText;
			} else {
				return null;
			}
		} else {
			return null;
		}
	}

	public long getLyricTime(int index) {
		if (mLyricLines != null) {
			if (index >= 0 && index < mLyricLines.size()) {
				return mLyricLines.get(index).mLyricTime;
			} else {
				return -1;
			}
		} else {
			return -1;
		}
	}

	public int getCurrentLyric() {
		return mCurrentLyric;
	}

	public void setListener(LyricListener listener) {
		mListener = listener;
	}

	// 由利用者调用，用来通知现在的播放时间，一边找到合适的歌词。
	public void notifyTime(long millisecond) {
		if (mLyricLines != null) {
			int newLyric = seekLyric(millisecond);
			Log.i(TAG, "newLyric = " + newLyric);
			if (newLyric != -1 && newLyric != mCurrentLyric) {// 如果找到的歌词和现在的不是一句。
				if (mListener != null) {
					// 告诉一声，歌词已经编程另外一句啦！
					mListener.onLyricChanged(newLyric);
				}
				mCurrentLyric = newLyric;
			}
		}
	}

	private int seekLyric(long millisecond) {
		int findStart = 0;
		if (mCurrentLyric >= 0) {
			// 如果已经指定当前字幕，则现在位置开始
			findStart = mCurrentLyric;
		}

		long lyricTime = mLyricLines.get(findStart).mLyricTime;

		if (millisecond > lyricTime) { // 如果想要查找的时间在现在字幕的时间之后
			// 如果开始位置经是最后一句了，直接返回最后一句。
			if (findStart == (mLyricLines.size() - 1))
				return findStart;

			int new_index = findStart + 1;
			// 找到第一句开始时间大于输入时间的歌词
			while (new_index < mLyricLines.size()
					&& mLyricLines.get(new_index).mLyricTime <= millisecond) {
				++new_index;
			}
			// 这句歌词的前一句就是我们要找的了。
			return new_index - 1;
		} else if (millisecond < lyricTime) { // 如果想要查找的时间在现在字幕的时间之前
			// 如果开始位置经是第一句了，直接返回第一句。
			if (findStart == 0)
				return 0;

			int new_index = findStart - 1;
			// 找到开始时间小于输入时间的歌词
			while (new_index > 0
					&& mLyricLines.get(new_index).mLyricTime > millisecond) {
				--new_index;
			}
			return new_index;
		} else {
			// 不用找了
			return findStart;
		}

	}
}
